
#include "aero_oled.h"
#include "oledFont.h"


extern unsigned char oledGram[128][8];
/*
 * DC 命令/数据  0:命令 1:数据
 * SPI模式下，每个数据长度为8位，在sclk的上升沿数据从SDIN移入，并且高位在前
 */

void delayy()
{
		asm("nop");
		asm("nop");

/*
    int m;
    		for (m=0;m<1;m++)
		{
			PORTB = 0X01;
			PORTB = 0X01;
			PORTB = 0X01;
			PORTB = 0X01;
			
		}
*/
}
//extern void delayms(unsigned int i);


void WriteCmd(unsigned char data)
{
	unsigned char i;
	ClrDcPin;
	delayy();	
	for(i=0;i<8;i++){
        ClrClkPin;
     	delayy();	

        if(data&0x80){
        	SetMosiPin;
        	delayy();	
        }
		else{
			ClrMosiPin;
        	delayy();	
        }

        SetClkPin;
    	delayy();	
        data<<=1;
	}
}

/*
 *
 */
void WriteData(unsigned char data)
{
	unsigned char i;
	SetDcPin;
	delayy();	

	for(i=0;i<8;i++){
		ClrClkPin;
    	delayy();	

        if(data&0x80){
        	SetMosiPin;
        	delayy();	

        }
		else{
			ClrMosiPin;
        	delayy();	
        }

        SetClkPin;
    	delayy();	
        data<<=1;
	}
}

/*
 * 复位
 */
void OledPor()
{
	//int i;
	SetResPin;
	/*
	 * 调用了系统定时器，因此如果使用usleep、sleep等系统函数需要对AMP下定时器设置正确
	 * 暂时删除usleep 30ms操作
	 */
	ClrResPin;
	SetResPin;
}

/*
 * 初始化操作
 */
void OledInit()
{	OledPor();
	WriteCmd(0xAE);//--turn off oled panel
	WriteCmd(0x02);//---set low column address
	WriteCmd(0x10);//---set high column address
	WriteCmd(0x40);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
	WriteCmd(0x81);//--set contrast control register
	WriteCmd(0xFF); // Set SEG Output Current Brightness
	WriteCmd(0xA1);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
	WriteCmd(0xC0);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
	WriteCmd(0xA6);//--set normal display
	WriteCmd(0xA8);//--set multiplex ratio(1 to 64)
	WriteCmd(0x3f);//--1/64 duty
	WriteCmd(0xD3);//-set display offset	Shift Mapping RAM Counter (0x00~0x3F)
	WriteCmd(0x00);//-not offset
	WriteCmd(0xd5);//--set display clock divide ratio/oscillator frequency
	WriteCmd(0x80);//--set divide ratio, Set Clock as 100 Frames/Sec
	WriteCmd(0xD9);//--set pre-charge period
	WriteCmd(0xF1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
	WriteCmd(0xDA);//--set com pins hardware configuration
	WriteCmd(0x12);
	WriteCmd(0xDB);//--set vcomh
	WriteCmd(0x40);//Set VCOM Deselect Level
	WriteCmd(0x20);//-Set Page Addressing Mode (0x00/0x01/0x02)
	WriteCmd(0x02);//
	WriteCmd(0x8D);//--set Charge Pump enable/disable
	WriteCmd(0x14);//--set(0x10) disable
	WriteCmd(0xA4);// Disable Entire Display On (0xa4/0xa5)
	WriteCmd(0xA6);// Disable Inverse Display On (0xa6/a7)
	WriteCmd(0xAF);//--turn on oled panel display on

}

/*
 * refresh gram to oled
 */
void OledRefreshGram(void)
{
	unsigned char i,n;
	for(i=0;i<8;i++){
		WriteCmd (0xb0+i);    //设置页地址（0~7）
		WriteCmd (0x02);      //设置显示位置—列低地址,偏移了2列
		WriteCmd (0x10);      //设置显示位置—列高地址
		for(n=0;n<128;n++)
			WriteData(oledGram[n][i]);
	}
}

/*
 * 清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!
 */
void OledClear(void)
{
	unsigned char i,n;
	for(i=0;i<8;i++)
		for(n=0;n<128;n++)
			oledGram[n][i]=0X00;
	OledRefreshGram();
}

/*
 * 点
 * x:0~127
 * y:0~63
 * t:1 填充 0,清空
 * ret 1: 超范围
 */
unsigned char OledDrawPoint(unsigned char x,unsigned char y,unsigned char t)
{
	unsigned char pos,bx,temp=0;
	if(x>127||y>63)
		return 1;//超出范围了.
	pos=7-y/8;
	bx=y%8;
	temp=1<<(7-bx);

	if(t)
		oledGram[x][pos]|=temp;
	else
		oledGram[x][pos]&=~temp;

	return 0;
}

/*
 * x1,y1,x2,y2 填充区域的对角坐标
 * 确保x1<=x2;y1<=y2 0<=x1<=127 0<=y1<=63
 * dot:0,清空;1,填充
 */
void OledFill(unsigned char x1,unsigned char y1,unsigned char x2,unsigned char y2,unsigned char dot)
{
	unsigned char x,y;
	for(x=x1;x<=x2;x++)
	{
		for(y=y1;y<=y2;y++)
			OledDrawPoint(x,y,dot);
	}
	OledRefreshGram();//更新显示
}

/*
 *在指定位置显示一个字符,包括部分字符
 *x:0~127
 *y:0~63
 *mode:0,反白显示;1,正常显示
 *size:选择字体 16/12
 */
void OledShowChar(unsigned char x,unsigned char y,unsigned char chr,unsigned char size,unsigned char mode)
{
	unsigned char temp,t,t1;
	unsigned char y0=y;
	chr=chr-' ';//得到偏移后的值

	for(t=0;t<size;t++){
		if(size==12)
			temp=asc2_1206[chr][t];  //调用1206字体
		else
			temp=asc2_1206[chr][t];		 //调用1608字体

		for(t1=0;t1<8;t1++){
			if(temp&0x80)
				OledDrawPoint(x,y,mode);
			else
				OledDrawPoint(x,y,!mode);

			temp<<=1;
			y++;
			if((y-y0)==size){
				y=y0;
				x++;
				break;
			}
		}
	}
}

//m^n函数
unsigned int mypow(unsigned char m,unsigned char n)
{
	unsigned int result=1;
	while(n--)result*=m;
	return result;
}

/*
 * 显示数字
 * 	x,y :起点坐标
 * 	num:数值(0~4294967295);
 * 	size：12：位1206字体，其他为1608字体
 */
void OledShowNum(unsigned char x,unsigned char y,unsigned int num,unsigned char len,unsigned char size,unsigned char mode)
{
	unsigned char t,temp;
	unsigned char enshow=0;
	for(t=0;t<len;t++){
		temp=(num/mypow(10,len-t-1))%10;

		if(enshow==0&&t<(len-1)){
			if(temp==0){
				OledShowChar(x+(size/2)*t,y,' ',size,mode);
				continue;
			}else
				enshow=1;
		}
		OledShowChar(x+(size/2)*t,y,temp+'0',size,mode);
	}
}

/*
 * 显示字符串
 * x,y:起点坐标
 * *p:字符串起始地址
 * 用16字体
 *
 */

void OledShowString(unsigned char x,unsigned char y,char *p,unsigned char mode)
{
	#define MAX_CHAR_POSX 128
	#define MAX_CHAR_POSY 64
	while(*p!='\0')
	{
		if(x>MAX_CHAR_POSX)
			{x=0;y+=12;}
		if(y>MAX_CHAR_POSY)
			{y=x=0;OledClear();}

		OledShowChar(x,y,*p,12,mode);
		x+=6;
		p++;
	}
}
